package com.janetfilter.core;

import com.janetfilter.core.commons.DebugInfo;
import com.janetfilter.core.plugin.PluginManager;

import java.lang.instrument.Instrumentation;
import java.util.Set;

/**
 * 初始化器类，负责框架的初始化工作
 * 包括设置日志、加载插件、注册转换器等
 */
public class Initializer {
    /**
     * 初始化框架
     * 
     * @param environment 环境配置对象，包含所有框架运行所需的配置信息
     */
    public static void init(Environment environment) {
        // 设置日志文件保存目录
        DebugInfo.useFile(environment.getLogsDir());
        // 记录环境信息
        DebugInfo.info(environment.toString());

        // 创建分发器，负责分发和管理所有的字节码转换请求
        Dispatcher dispatcher = new Dispatcher(environment);
        // 创建插件管理器并加载所有插件
        new PluginManager(dispatcher, environment).loadPlugins();

        // 获取Instrumentation实例
        Instrumentation inst = environment.getInstrumentation();
        // 注册分发器作为类文件转换器
        // 参数true表示这个转换器可以重新转换已加载的类
        inst.addTransformer(dispatcher, true);
        // 设置native方法前缀，所有native方法在调用前会添加这个前缀
        // 这样可以拦截native方法的调用
        inst.setNativeMethodPrefix(dispatcher, environment.getNativePrefix());

        // 获取所有需要转换的类名
        Set<String> classSet = dispatcher.getHookClassNames();
        // 对已加载的类进行重新转换(retransform)
        for (Class<?> c : inst.getAllLoadedClasses()) {
            String name = c.getName();
            if (!classSet.contains(name)) {
                continue;
            }

            try {
                // 调用getGenericSuperclass()可以触发类的初始化
                c.getGenericSuperclass();
                // 重新转换类，应用字节码修改
                // 这个API是Java Instrumentation提供的关键功能之一
                // 允许在类已经加载后修改其字节码
                inst.retransformClasses(c);
            } catch (Throwable e) {
                DebugInfo.error("Retransform class failed: " + name, e);
            }
        }
    }
}
